/* Copyright (c) 2004-2024 peigen.info. All rights reserved. */

package info.peigen.hotpot.common.service.base.test;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import info.peigen.hotpot.common.core.result.ListResult;
import info.peigen.hotpot.common.core.result.ResultCode;
import info.peigen.hotpot.common.core.result.SingleResult;
import info.peigen.hotpot.common.service.base.test.mock.ServiceTestMockContext;
import info.peigen.hotpot.common.service.base.test.mock.ServiceTestMockContextThreadLocal;
import jakarta.validation.ConstraintViolationException;
import org.junit.jupiter.api.Assertions;

import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;

import static com.alibaba.fastjson2.JSONWriter.Feature.PrettyFormat;
import static info.peigen.hotpot.common.core.result.ResultCode.PARAMETER_ERROR;

/**
 * <b>(ServiceTestInvoke)</b>
 *
 * @author Peigen
 * @version 1.0.0
 * @since 2021/5/2
 */
@SuppressWarnings({"rawtypes", "unused"})
public interface ServiceTestInvoke {
    /**
     * 清除数据
     */
    void cleanData();

    /**
     * 初始化数据
     *
     * @param serviceTestContext 测试上下文
     */
    default void initData(ServiceTestContext serviceTestContext) {
    }

    /**
     * 获取渠道
     *
     * @param serviceTestContext 测试上下文
     */
    void callService(ServiceTestContext serviceTestContext) throws NoSuchAlgorithmException, InvalidKeyException;

    /**
     * 打印日志
     *
     * @param serviceTestContext 测试上下文
     */
    default void printLog(ServiceTestContext serviceTestContext) {
        if (ObjectUtil.isAllEmpty(serviceTestContext.getResultBase(), serviceTestContext.getSingleResult(), serviceTestContext.getListResult(), serviceTestContext.getPageResult())) {
            return;
        }
        if (ObjectUtil.isNotNull(serviceTestContext.getResultBase())) {
            System.out.println("\n" + serviceTestContext.getResultBase().getClass()
                    .getSimpleName() + "=\n" + JSON.toJSONString(serviceTestContext.getResultBase(), PrettyFormat));
        }
        if (ObjectUtil.isNotNull(serviceTestContext.getSingleResult())) {
            System.out.println("\n" + serviceTestContext.getSingleResult().getClass()
                    .getSimpleName() + "=\n" + JSON.toJSONString(serviceTestContext.getSingleResult(), PrettyFormat));
        }
        if (ObjectUtil.isNotNull(serviceTestContext.getListResult())) {
            System.out.println("\n" + serviceTestContext.getListResult().getClass()
                    .getSimpleName() + "=\n" + JSON.toJSONString(serviceTestContext.getSingleResult(), PrettyFormat));
        }
        if (ObjectUtil.isNotNull(serviceTestContext.getPageResult())) {
            System.out.println("\n" + serviceTestContext.getPageResult().getClass()
                    .getSimpleName() + "=\n" + JSON.toJSONString(serviceTestContext.getPageResult(), PrettyFormat));
        }
    }

    /**
     * 返回值校验
     *
     * @param serviceTestContext 测试上下文
     */
    default void resultAssert(ServiceTestContext serviceTestContext) {
        switch (serviceTestContext.getResultCode()) {
            case SUCCESS:
                Assertions.assertFalse(ObjectUtil.isAllEmpty(serviceTestContext.getResultBase(), serviceTestContext.getSingleResult(), serviceTestContext.getListResult(), serviceTestContext.getPageResult()));
                if (ObjectUtil.isNotNull(serviceTestContext.getResultBase())) {
                    Assertions.assertTrue(serviceTestContext.getResultBase().success());
                    Assertions.assertTrue(StrUtil.equalsIgnoreCase(serviceTestContext.getResultCode()
                            .code(), serviceTestContext.getResultBase().getCode()));
                }
                if (ObjectUtil.isNotNull(serviceTestContext.getSingleResult())) {
                    Assertions.assertTrue(serviceTestContext.getSingleResult().success());
                    Assertions.assertTrue(StrUtil.equalsIgnoreCase(serviceTestContext.getResultCode()
                            .code(), serviceTestContext.getSingleResult().getCode()));
                }
                if (ObjectUtil.isNotNull(serviceTestContext.getListResult())) {
                    Assertions.assertTrue(serviceTestContext.getListResult().success());
                    Assertions.assertTrue(StrUtil.equalsIgnoreCase(serviceTestContext.getResultCode()
                            .code(), serviceTestContext.getListResult().getCode()));
                }
                if (ObjectUtil.isNotNull(serviceTestContext.getPageResult())) {
                    Assertions.assertTrue(serviceTestContext.getPageResult().success());
                    Assertions.assertTrue(StrUtil.equalsIgnoreCase(serviceTestContext.getResultCode()
                            .code(), serviceTestContext.getPageResult().getCode()));
                }
                break;
            // 如果返回失败
            case FAILURE:
            case PARAMETER_ERROR:
            case CHANNEL_GATEWAY_ERROR:
            case CHANNEL_TIMEOUT:
                if (ObjectUtil.isNotNull(serviceTestContext.getSingleResult())) {
                    Assertions.assertTrue(serviceTestContext.getSingleResult().failure());
                    Assertions.assertEquals(serviceTestContext.getResultStatus(), serviceTestContext.getSingleResult()
                            .getStatus());
                    Assertions.assertEquals(serviceTestContext.getResultCode(), ResultCode.getByCode(serviceTestContext
                            .getSingleResult().getCode()));
                }
                if (ObjectUtil.isNotNull(serviceTestContext.getListResult())) {
                    Assertions.assertTrue(serviceTestContext.getListResult().failure());
                    Assertions.assertEquals(serviceTestContext.getResultStatus(), serviceTestContext.getListResult()
                            .getStatus());
                    Assertions.assertEquals(serviceTestContext.getResultCode(), ResultCode.getByCode(serviceTestContext
                            .getListResult().getCode()));
                }
                break;

            // 其他状态
            default:

        }
    }

    /**
     * 数据校验
     *
     * @param serviceTestContext 测试上下文
     */
    default void dataAssert(ServiceTestContext serviceTestContext) {
    }

    /**
     * 异常校验
     *
     * @param e                  异常
     * @param serviceTestContext 测试上下文
     */
    default void exceptionAssert(Exception e, ServiceTestContext serviceTestContext) {
        ServiceTestMockContext mockContext = ServiceTestMockContextThreadLocal.currentContext();

        if (ConstraintViolationException.class == e.getClass()) {
            if (PARAMETER_ERROR == mockContext.getExpectResultCode()) {
                return;
            }
            Assertions.assertEquals(PARAMETER_ERROR, mockContext.getExpectResultCode());
        }
        e.printStackTrace();

        if (ObjectUtil.isNotNull(serviceTestContext.getListResult())) {
            serviceTestContext.getListResult().setFail(e.getMessage());
        } else {
            ListResult listResult = new ListResult();
            listResult.setFail(e.getMessage());
            serviceTestContext.setListResult(listResult);
        }

        if (ObjectUtil.isNotNull(serviceTestContext.getSingleResult())) {
            serviceTestContext.getSingleResult().setFail(e.getMessage());
        } else {
            SingleResult singleResult = new SingleResult();
            singleResult.setFail(e.getMessage());
            serviceTestContext.setSingleResult(singleResult);
        }
    }

}